home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / oscar / rendezvous / directim.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  10KB  |  228 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. from util import Packable, strlist, lookup_table, bitflags_enabled, myip, callsback
  6. from oscar.rendezvous.peer import OscarPeer
  7. from oscar.rendezvous.rendezvous import rendezvous_tlvs
  8. from oscar.OscarUtil import tlv_list
  9. import oscar
  10. import common
  11. import time
  12. import struct
  13. from logging import getLogger
  14. log = getLogger('oscar.directim')
  15. info = log.info
  16. import os.path as os
  17. import wx
  18. from util.BeautifulSoup import BeautifulSoup
  19. from functools import partial
  20. from oscar import OscarException
  21. from common.Protocol import StateMixin
  22.  
  23. def directconnect(protocol, screenname):
  24.     if not isinstance(screenname, str):
  25.         raise TypeError('screenname must be a str')
  26.     
  27.     
  28.     ostrip = lambda s: s.lower().replace(' ', '')
  29.     if ostrip(screenname) == ostrip(protocol.self_buddy.name):
  30.         raise OscarException('You cannot direct connect with yourself.')
  31.     
  32.     cookie = int(time.time() ** 2)
  33.     protocol.rdv_sessions[cookie] = dim = OscarDirectIM(protocol, screenname, cookie)
  34.     dim.request()
  35.     return dim
  36.  
  37.  
  38. class ODCHeader(Packable):
  39.     fmt = strlist('\n        version    4s      # always ODC2\n        hdrlen     H       # length of header\n        one        H       # 1\n        six        H       # 6\n        zero       H       # 0\n        cookie     Q       # sixteen byte rendezvous cookie\n        null       Q\n        length     I\n        encoding   H\n        subset     H\n        flags      I\n        zero       I\n        screenname 16s\n        null2      16s ')
  40.     
  41.     def make(cls, *a, **k):
  42.         k.update(dict(version = 'ODC2', static = 76, one = 1, six = 6, zero = 0, null = 0, null2 = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
  43.         return cls(*a, **k)
  44.  
  45.     make = classmethod(make)
  46.     bitflags = lookup_table({
  47.         1: 'autoresponse',
  48.         2: 'typingpacket',
  49.         4: 'typed',
  50.         8: 'typing',
  51.         32: 'confirmation',
  52.         64: 'mac_confirmation' })
  53.     invars = [
  54.         (lambda o: o.version == 'ODC2')]
  55.  
  56.  
  57. class OscarDirectIM(OscarPeer, StateMixin):
  58.     
  59.     class Statuses:
  60.         DISCONNECTED = 'Disconnected'
  61.         CONNECTING = 'Connecting'
  62.         ERROR = 'Error'
  63.         CONNECTED = 'Connected'
  64.         OFFLINE = DISCONNECTED
  65.  
  66.     
  67.     class Reasons:
  68.         NONE = 'None'
  69.  
  70.     
  71.     def __init__(self, protocol, screenname, cookie):
  72.         StateMixin.__init__(self, self.Statuses.CONNECTING)
  73.         direct_im_cap = oscar.capabilities.by_name['direct_im']
  74.         OscarPeer.__init__(self, protocol, screenname, cookie, direct_im_cap)
  75.         self.buddy = protocol.buddies[screenname]
  76.  
  77.     
  78.     def accept(self):
  79.         info('%r accepted', self)
  80.         self.establish_dc()
  81.  
  82.     
  83.     def handle_request(self, rendtlvs):
  84.         self.send_rdv('cancel')
  85.  
  86.     
  87.     def setup_convo(self):
  88.         self.convo = self.protocol.convo_for(self.screenname)
  89.         self.convo.setnotifyif('type', 'dc')
  90.         self.convo.dc = self
  91.         self.change_state(self.Statuses.CONNECTED)
  92.  
  93.     
  94.     def on_odc_connection(self):
  95.         self.socket.receive_next(ODCHeader, self.odc_header_received)
  96.         self.setup_convo()
  97.         self.send_odc(flags = 96)
  98.  
  99.     
  100.     def odc_header_received(self, data):
  101.         (packet, data) = ODCHeader.unpack(data)
  102.         flags = bitflags_enabled(ODCHeader.bitflags, packet.flags)
  103.         info('incoming ODC header - enabled flags: %s', ', '.join(flags))
  104.         typeset = partial(self.convo.set_typing_status, self.screenname)
  105.         if 'typingpacket' in flags:
  106.             if 'typing' in flags:
  107.                 typeset('typing')
  108.             elif 'typed' in flags:
  109.                 typeset('typed')
  110.             else:
  111.                 typeset(None)
  112.         
  113.         next = self.socket.receive_next
  114.         leftover = packet.hdrlen - ODCHeader._struct.size
  115.         if leftover:
  116.             next(leftover, self.read_leftover(packet.length))
  117.         elif packet.length > 0:
  118.             next(packet.length, self.odc_body_received)
  119.         else:
  120.             next(ODCHeader, self.odc_header_received)
  121.  
  122.     
  123.     def read_leftover(self, paklen):
  124.         info('read %d leftover bytes', paklen)
  125.         next = self.socket.receive_next
  126.         
  127.         def callback(data):
  128.             if paklen > 0:
  129.                 next(paklen, self.odc_body_received)
  130.             else:
  131.                 next(ODCHeader, self.odc_header_received)
  132.  
  133.         return callback
  134.  
  135.     
  136.     def odc_body_received(self, data):
  137.         info('odc_body_received')
  138.         assetdir = wx.StandardPaths.Get().GetUserDataDir()
  139.         if '<BINARY>' in data:
  140.             j = data.find('<BINARY>')
  141.             soup = BeautifulSoup(data[:j])
  142.             for img in soup.html.body('img'):
  143.                 imgdata = data[j:]
  144.                 findme = ' ID="%s" SIZE="%s">' % (str(img['id']), str(img['datasize']))
  145.                 i = imgdata.find(findme)
  146.                 imgbytes = imgdata[i + len(findme):int(img['datasize']) + 33]
  147.                 imgpath = os.path.join(assetdir, os.path.split(img['src'])[1])
  148.                 img['src'] = imgpath
  149.                 del img['width']
  150.                 del img['height']
  151.                 
  152.                 try:
  153.                     f = _[2]
  154.                     f.write(imgbytes)
  155.                 finally:
  156.                     pass
  157.  
  158.             
  159.             msg = unicode(soup.html)
  160.         else:
  161.             msg = data
  162.         self.convo.incoming_message(self.screenname, msg)
  163.         self.socket.receive_next(ODCHeader, self.odc_header_received)
  164.  
  165.     
  166.     def send_odc(self, data = '', flags = 0):
  167.         bname = self.protocol.self_buddy.name
  168.         packet = ODCHeader.make(cookie = self.cookie, screenname = bname)
  169.         packet.flags = flags
  170.         if isinstance(data, list):
  171.             packet.length = sum((lambda .0: for d in .0:
  172. len(d))(data))
  173.             info('send_odc got a list, summed length is %d', packet.length)
  174.         else:
  175.             packet.length = len(data)
  176.             info('send_odc got a string, length is %d', packet.length)
  177.         packet.hdrlen = len(packet)
  178.         info('sending ODC header to screenname %s (%d bytes of %r)', bname, len(packet), str(type(packet)))
  179.         if isinstance(data, list):
  180.             self.socket.push(packet.pack() + ''.join(data))
  181.         else:
  182.             self.socket.push(packet.pack() + data)
  183.  
  184.     
  185.     def send_typing(self, status):
  186.         flag = {
  187.             'typing': 8,
  188.             'typed': 4,
  189.             None: 0 }[status]
  190.         self.send_odc(flags = 2 | flag)
  191.  
  192.     
  193.     def request(self):
  194.         self.establish_out_dc()
  195.  
  196.     
  197.     def ch2accept(self, data):
  198.         info('incoming dIM got channel 2 accept')
  199.  
  200.     
  201.     def send_message(self, message):
  202.         self.send_odc(message)
  203.  
  204.     
  205.     def decline(self):
  206.         self.send_rdv('cancel')
  207.  
  208.     
  209.     def ch2cancel(self, data):
  210.         info('%r cancelled', self)
  211.         if hasattr(self, 'convo'):
  212.             self.convo.setnotifyif('type', 'im')
  213.         
  214.         self.change_state(self.Statuses.DISCONNECTED)
  215.  
  216.     
  217.     def disconnect(self):
  218.         self.socket.close()
  219.         del self.convo.dc
  220.         self.convo.setnotifyif('type', 'im')
  221.         self.change_state(self.Statuses.DISCONNECTED)
  222.  
  223.     
  224.     def __repr__(self):
  225.         return '<OscarDirectIM with %s>' % self.screenname
  226.  
  227.  
  228.